#pragma once

#include <iostream>
#include <cstdlib>
#include <cassert>

// clear transposition table of all entries, create blank entries
void clear_table_transposition(I_TABLE_TRANSPOSITION t)
{
	for (int i = 0; i < I_TABLE_TRANS_SIZE; ++i)
	t[i].etype = NULL_ENTRY;
};

// clear history table of all entries, fill with zeroes
void clear_table_history(I_TABLE_HISTORY h)
{ memset(h, 0, I_BOARD_TRUE * I_BOARD_TRUE); };

// look up the board in the transposition table: return in the move, if it is correct
bool trans_recall(I_CHESS_POSITION *p, I_CHESS_MOVE *m)
{
	// get data from the global search agent
	I_TABLE_TRANS_ENTRY *t = GAME.SEARCH_AGENT.trans;
	
	// generate short-key
	int key = board_hash(p) & I_TABLE_TRANS_MASK;
	
	if (t[key].etype == NULL_ENTRY) return false;
	if (t[key].lock != board_lock(p)) return false;
	
	m->eval = t[key].eval;
	m->etype = t[key].etype;
	m->depth = t[key].depth;
	
	return true;
};

// store the current board in the transposition table, as well as the evaluation and depth
void trans_save(I_CHESS_POSITION *p, int eval, int etype, int depth)
{
	// get data from the global search agent
	I_TABLE_TRANS_ENTRY *t = GAME.SEARCH_AGENT.trans;
	int stamp = p->halfmoves;
	
	// generate short-key
	int key = board_hash(p) & I_TABLE_TRANS_MASK;
	
	// if this is going to overwrite a position that is ultimately more useful, forget it...
	if (t[key].etype != NULL_ENTRY && t[key].depth <= depth && t[key].stamp < stamp) return;
	
	t[key].lock = board_lock(p);
	t[key].eval = eval;
	t[key].etype = etype;
	t[key].depth = depth;
	t[key].stamp = stamp;
};

// add strength to this move in the history table, so that it will be searched first
void add_count(I_CHESS_MOVE *m)
{ ++GAME.SEARCH_AGENT.hist[convert_144_to_64(m->index[MOVE_FROM])][convert_144_to_64(m->index[MOVE_TO])]; };
